home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
www
/
ludzie
/
txf
/
progs
/
savenames.lha
/
SaveNames1.5
/
SaveNames.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-12-12
|
23KB
|
880 lines
/**************************************************************************
* *
* Save Names 1.5 *
* ---------------- *
* *
* SaveNames is freely distributable but is copyrighted by its author, *
* Marcin Orlowski (carlos@dedal.man.szczecin.pl). For more information *
* read the short documentation included in this archive. SaveNames is *
* written in ANSI C, so may be compiled on any machine, except for pc *
* (do you see any sense? :). Unfortunately small changes must sometimes *
* be done before you run the compiler. Look below, and select your *
* platform. AMIGA side was tested on A4000, UNIX side was tested on IRIS *
* INDIGO, HP, SunOS (compiles harmless, however with small exceptions ). *
* The LINUX side was tested... on LINUX :-). *
* *
* Use and enjoy... *
* *
* Any suggestions, bugs, mails or anything else send to: *
* *
* Marcin Orlowski Tadek Knapik *
* Radomska 38 Duza Gora 35/88 *
* 71-002 Szczecin 30-857 Krakow *
* Poland Poland *
* *
* or via net: *
* *
* carlos@dedal.man.szczecin.pl tadek@student.uci.agh.edu.pl *
* http://www.szczecin.pl/~carlos *
* *
* FidoNet: Marcin Orlowski@2:481/22.2 *
* GlobalNet: Marcin Orlowski@52:4800/6 *
* *
* or try Silver Dream!'s BBS (non-stop) at +48 91 540431 *
* *
*************************************************************************/
/* Define your favourite platform (except Amiga :-) */
#define AMIGA
/* NOTE: LINUX and SUNOS automagically defines
UNIX by itself, so you don't need to
uncomment it by hand!
#define AMIGA
#define LINUX
#define SUNOS
#define UNIX
*/
/* Uncomment this only for compilers requiring C&R declaration type */
/*
#define OLD_STYLE
*/
/*************************************************************************/
#ifdef AMIGA
char __stdiowin[] = "con:0/15/500/230/W.F.M.H. SaveNames 1.5";
char verstring[] = "$VER: SaveNames 1.5 (11.12.96)";
#define CURRENTDIR ""
#include <sys/dir.h>
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_WARN
#define EXIT_WARN 5
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 20
#endif
/* Do not touch this if you don't know what you are doing! */
/*
#ifdef MAXNAMELEN
#undef MAXNAMELEN
#endif
#define MAXNAMELEN 108
*/
#endif
/*************************************************************************/
#ifdef LINUX
#include <unistd.h>
#ifndef UNIX
#define UNIX
#endif
#endif
/*************************************************************************/
#ifdef SUNOS
#ifndef UNIX
#define UNIX
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 20
#endif
#endif
/*************************************************************************/
#ifdef UNIX
#ifdef CURRENTDIR
#undef CURRENTDIR
#endif
#define CURRENTDIR "."
#define PARENTDIR ".."
#include <dirent.h>
#include <sys/types.h>
#endif
/*************************************************************************/
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef RC_OK
#define RC_OK 0 /* Tadek was here */
#endif
#define RC_SPLITERROR 1
#define RC_CRAZY 2
#define RC_CRAZY_COOL 3
#ifndef RC_FAIL
#define RC_FAIL 4
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE ~TRUE
#endif
/*************************************************************************/
#define AMI_DD_OFS 853000 /* Capacity of various floppy disks */
#define AMI_DD_FFS 880000 /* This values may not fit exactly, */
#define AMI_HD_FFS 1780000 /* but it doesn't matter so much... */
#define PC_DD 725000 /* In case of big number of files, */
#define PC_HD 1455000 /* the disk space is going down, 'cos */
/* The capacity of pee-see floppy may differ, depending on the formatter
etc. If you format it on Amiga using multi_os.device you may want to
use the following values (don't forger to delete definitions above!):
#define PC_HD 1440000
#define PC_DD 710000
*/
/* of file headers and similar things */
/* Tadek: 3 next #defines */
#define PC_HD_FIT 1440000 /* this is for max file sizes - a little bit */
#define PC_DD_FIT 710000 /* lower, so it fits on disk for sure */
#define DISKS_MAX 999 /* you can't have more.. */
#define PCNAME 12 /* 8 + . + 3 */
FILE *FileHandle = NULL;
DIR *dfd; /* directory descriptor */
int fh; /* FileHandle */
struct dirent *dptr; /* dir entry */
struct stat *st = NULL; /* file information */
char TempBuff[PCNAME+1]; /* +1 because of trailing NULL */
char CurrentDir[MAXNAMLEN+2];
struct Entry *FirstEntry= NULL; /* for queue of entrires... */
struct Entry *LastEntry = NULL;
struct Entry *TempEntry = NULL;
struct Entry *Temp2 = NULL;
struct Entry /* ... like this one... */
{
struct Entry *Next; /* Successor */
char INode[PCNAME+1]; /* Almost unique file ID */
char Name[MAXNAMLEN+1]; /* Original file name */
};
int Index; /* Universal counter */
int Count = 0, SkipCount = 0; /* Almost universal counters :) */
unsigned long TotalSize = 0; /* Guess yourself... */
char ErrorHeader = TRUE;
char DecodeResult;
/* Tadek - declarations */
int splitname(char s[], char t[], int splitsize);
int rejoinname(char s[], char t[]);
int namecount(char s[], char t[], int diskcount);
FILE *SpareIdx = NULL;
char newname[MAXNAMLEN];
int rc = NULL;
int splitsize = NULL;
int SplitCount = NULL;
/*************************************************************************/
#ifdef OLD_STYLE
void main(args, argv)
int args;
char **argv;
#else
void main(int args, char **argv)
#endif
{
printf("\n");
printf("SaveNames 1.5 by Marcin Orlowski & Tadek Knapik\n");
printf("E-Mail: carlos@dedal.man.szczecin.pl\n");
printf(" or: tadek@student.uci.agh.edu.pl\n\n");
if((args < 3) || (args > 4))
{
#ifdef AMIGA
if(args == 0)
printf("** Can't be run from Workbench.\n\n");
#endif
#ifdef UNIX
printf("Type 'man SaveNames'");
#else
printf("Read file 'SaveNames.doc'");
#endif
printf(" to get whole documentation\n\n");
if(strlen(argv[0]))
printf("Usage: %s ", argv[0]);
else
printf("Shell Usage: SaveNames ");
printf("Command DirName <SplitSize>\n");
printf("Command - type 'C' or 'CODE' to crypt names (and optionally split files) \n");
printf(" type '-C' or '-COUNT' to count disks usage only\n");
printf(" type 'D' or 'DECODE' to restore names and rejoin files\n");
printf(" type '-D' or '-DECODE' for expanded restore (also with rejoin)\n");
printf("DirName - process contents of this directory\n");
printf("SplitSize - (optional) maximum size of output files (larger files will\n");
printf(" be splitted) or just 'DD'/'HD' (default PC sizes)\n\n");
exit(EXIT_FAILURE);
}
getcwd(CurrentDir, sizeof(CurrentDir));
if(chdir(argv[2]))
{
printf("** Can't find directory.\n");
exit(EXIT_FAILURE);
}
if(argv[1][0] == 'C' || argv[1][0] == 'c' || (argv[1][0] == '-' && argv[1][1] == 'C') || (argv[1][0] == '-' && argv[1][1] == 'c'))
{
if((dfd = opendir(CURRENTDIR)))
{
char running = TRUE;
FileHandle = NULL;
if((FileHandle = fopen("WFMHFile.idx", "r")) == NULL)
if((FileHandle = fopen("wfmhfile.idx", "r")) == NULL)
FileHandle = fopen("WFMHFILE.IDX", "r");
if(argv[1][0] == 'C' || argv[1][0] == 'c')
{
if(FileHandle)
{
fclose(FileHandle);
printf("** Index file found in drawer '%s'.\n", argv[2]);
printf("** It means you have already coded filenames.\n");
printf("** Because this operation cannot be nested\n");
printf("** it has been aborted. Watch your moves!\n");
chdir(CurrentDir);
exit(EXIT_FAILURE);
}
}
/*
** Tadek: <SplitSize> handling
*/
if (args == 4)
{
if (((strcmp(argv[3],"DD")) == 0) || ((strcmp(argv[3],"dd")) == 0) || ((strcmp(argv[3],"Dd")) == 0) || ((strcmp(argv[3],"dD")) == 0))
splitsize = PC_DD;
else if (((strcmp(argv[3],"HD")) == 0) || ((strcmp(argv[3],"hd")) == 0) || ((strcmp(argv[3],"Hd")) == 0) || ((strcmp(argv[3],"hD")) == 0))
splitsize = PC_HD;
else
splitsize = atoi(argv[3]);
}
/*
** end of splitsize handling
*/
if(argv[1][0] == '-')
printf("Counting floppy disks usage ...\n");
else
{
printf("Coding filenames");
if (splitsize) /* Tadek was here */
printf(" (with splitsize %d bytes)", splitsize);
printf("...\n");
}
Count = 0;
if((st = malloc(sizeof(struct stat))) == NULL)
printf(" ** No length counting. No memory for structure.\n");
while((dptr = readdir(dfd)) && running)
{
#ifdef UNIX
if((strcmp(dptr->d_name, CURRENTDIR) != 0) && (strcmp(dptr->d_name, PARENTDIR) != 0))
{
#endif
if((TempEntry = (struct Entry *)malloc(sizeof(struct Entry))))
{
strcpy(TempEntry->Name, dptr->d_name);
sprintf(TempEntry->INode, "%lx.pcp", dptr->d_ino);
if(!(FirstEntry))
FirstEntry = TempEntry;
else
LastEntry->Next = TempEntry;
LastEntry = TempEntry;
TempEntry->Next = NULL;
if(st)
if(fh = open(dptr->d_name, O_RDONLY, 0))
{
if(fstat(fh, st) == 0)
TotalSize += st->st_size;
close(fh);
}
Count++;
}
else
{
printf("** Out of memory. %d files scanned.\n", Count);
printf("** Skipping the rest of files.\n");
running = FALSE;
}
#ifdef UNIX
}
#endif
}
closedir(dfd);
if(st)
{
if(TotalSize != 0)
{
int KB = (TotalSize/1024);
int MB = (TotalSize/1048576);
printf("\n Disks summary for %ld files (%ld bytes", Count, TotalSize);
if(KB) printf(", %d KB", KB);
if(MB) printf(", %d MB", MB);
printf(")\n\n");
printf(" Disk type Capacity Cnt Free on last\n");
printf(" ------------------------------------------\n");
printf(" Amiga DD (OFS) %8ld %3ld %9ld KB\n", AMI_DD_OFS, (AMI_DD_OFS + TotalSize) / AMI_DD_OFS, (AMI_DD_OFS * ((AMI_DD_OFS + TotalSize) / AMI_DD_OFS) - TotalSize)/1024);
printf(" Amiga DD (FFS) %8ld %3ld %9ld KB\n", AMI_DD_FFS, (AMI_DD_FFS + TotalSize) / AMI_DD_FFS, (AMI_DD_FFS * ((AMI_DD_FFS + TotalSize) / AMI_DD_FFS) - TotalSize)/1024);
printf(" Amiga HD (FFS) %8ld %3ld %9ld KB\n", AMI_HD_FFS, (AMI_HD_FFS + TotalSize) / AMI_HD_FFS, (AMI_HD_FFS * ((AMI_HD_FFS + TotalSize) / AMI_HD_FFS) - TotalSize)/1024);
printf(" pc DD %8ld %3ld %9ld KB\n", PC_DD, (PC_DD + TotalSize) / PC_DD, (PC_DD * ((PC_DD + TotalSize) / PC_DD) - TotalSize)/1024);
printf(" pc HD %8ld %3ld %9ld KB\n\n", PC_HD, (PC_HD + TotalSize) / PC_HD, (PC_HD * ((PC_HD + TotalSize) / PC_HD) - TotalSize)/1024);
}
else
printf("No files - no summary :-(...\n");
}
if(st)
{
free(st);
st = NULL;
}
if(argv[1][0] == '-') /* We wanted summary only */
{
TempEntry = FirstEntry;
while(TempEntry)
{
Temp2 = TempEntry->Next;
free(TempEntry);
TempEntry = Temp2;
}
chdir(CurrentDir);
exit(EXIT_SUCCESS);
}
if(FileHandle = fopen("WFMHFile.idx", "w"))
{
Count = 0;
TempEntry = FirstEntry;
/*
** Tadek: my function is put instead of rename(), and I messed a little
** bit with the error handling
*/
while(TempEntry)
{
if((rc = splitname(TempEntry->Name, TempEntry->INode, splitsize)) != RC_OK)
{
#ifdef UNIX
if((strcmp(TempEntry->Name, CURRENTDIR) != 0) && (strcmp(TempEntry->Name, PARENTDIR) != 0))
{
#endif
if(ErrorHeader == TRUE)
{
printf("I had troubles with following files:\n");
printf("-------------------------------------\n");
ErrorHeader = FALSE;
}
if (rc == RC_FAIL)
{
printf("Can't rename '%s'\n", TempEntry->Name);
SkipCount++;
}
else
{
if ((rc == RC_SPLITERROR) || (rc == RC_CRAZY_COOL))
{
fprintf(FileHandle, "%s%c%s\n", TempEntry->INode, 0x09, TempEntry->Name);
Count++;
}
if (rc == RC_SPLITERROR)
{
printf("Can't split '%s'\n", TempEntry->Name);
}
else if ((rc == RC_CRAZY) || (rc == RC_CRAZY_COOL))
printf("Splitsize too small for '%s'\n", TempEntry->Name);
}
}
#ifdef UNIX
}
#endif
else
{
fprintf(FileHandle, "%s%c%s\n", TempEntry->INode, 0x09, TempEntry->Name);
Count++;
}
Temp2 = TempEntry->Next;
free(TempEntry);
TempEntry = Temp2;
}
/*
** Tadek: Processed files report - changed a little bit
*/
fclose(FileHandle);
if(Count)
if(SplitCount)
printf("%d files processed (%d of them splitted)\n", Count, SplitCount);
else
{
printf("%d files processed", Count);
if (splitsize)
printf(" (none splitted)");
printf("\n");
}
if(SkipCount)
printf("%d files skipped\n", SkipCount);
if(Count)
printf("Done.\n");
}
else
{
TempEntry = FirstEntry;
while(TempEntry);
{
Temp2 = TempEntry->Next;
free(TempEntry);
TempEntry = Temp2;
}
printf("** Can't open index file to write 'WFMHFile.idx'.\n");
chdir(CurrentDir);
exit(EXIT_FAILURE);
}
}
else
{
printf("** Can't open directory '%s'.\n", argv[2]);
chdir(CurrentDir);
exit(EXIT_FAILURE);
}
}
/* ########### DECODING PART BEGINS ############## */
else
if(argv[1][0] == 'D' || argv[1][0] == 'd' || (argv[1][0] == '-' && argv[1][1] == 'D') || (argv[1][0] == '-' && argv[1][1] == 'd'))
{
if((TempEntry = malloc(sizeof(struct Entry))))
{
if((FileHandle = fopen("WFMHFile.idx", "r")) == NULL)
if((FileHandle = fopen("wfmhfile.idx", "r")) == NULL)
FileHandle = fopen("WFMHFILE.IDX", "r");
if(FileHandle)
{
if(argv[1][0] == '-')
printf("Decoding filenames in expanded mode...\n");
else
printf("Decoding filenames...\n");
Count = 0;
while(EOF != fscanf(FileHandle, "%s", TempEntry->INode))
{
do
TempEntry->Name[0] = getc(FileHandle);
while((TempEntry->Name[0] != 0xa) && (TempEntry->Name[0] != 9));
for(Index=0; Index<MAXNAMLEN; Index++)
{
TempEntry->Name[Index] = fgetc(FileHandle);
if(((TempEntry->Name[Index]) == 0xa) || (TempEntry->Name[Index] == EOF))
break;
}
TempEntry->Name[Index] = 0x00;
/*
** Tadek: again my function instead of rename()
*/
if(rejoinname(TempEntry->INode, TempEntry->Name))
{
DecodeResult = FALSE;
if(argv[1][0] == '-')
{
Index = 0;
while(TempEntry->INode[Index] != '\0')
{
TempEntry->INode[Index] = tolower((int)TempEntry->INode[Index]);
Index++;
}
if(rejoinname(TempEntry->INode, TempEntry->Name))
{
Index = 0;
while(TempEntry->INode[Index] != '\0')
{
TempEntry->INode[Index] = toupper((int)TempEntry->INode[Index]);
Index++;
}
if(rejoinname(TempEntry->INode, TempEntry->Name) == 0)
{
Count++;
DecodeResult = TRUE;
}
}
}
if(DecodeResult == FALSE)
{
if(ErrorHeader == TRUE)
{
printf("I can't restore following files:\n");
printf("--------------------------------\n");
SpareIdx = fopen("WFMHFil2.idx", "w");
ErrorHeader = FALSE;
}
printf("'%s'\n", TempEntry->Name);
SkipCount++;
if (SpareIdx)
fprintf(SpareIdx, "%s%c%s\n", TempEntry->INode, 0x09, TempEntry->Name);
}
}
else
Count++;
}
fclose(FileHandle);
free(TempEntry);
if(Count)
{
printf("%d files restored", Count);
if (SplitCount)
printf(" (%d of them rejoined)", SplitCount);
printf("\n");
}
if(SkipCount)
printf("%d files skipped\n", SkipCount);
if(Count)
printf("Done.\n");
if(SkipCount == 0)
{
if(remove("WFMHFile.idx") != 0)
if(remove("wfmhfile.idx") != 0)
if(remove("WFMHFILE.IDX") != 0)
{
printf("** Can't remove index file.\n");
chdir(CurrentDir);
#ifdef AMIGA
exit(EXIT_WARN);
#endif
}
}
else
{
if (SpareIdx)
{
if(remove("WFMHFile.idx") != 0)
if(remove("wfmhfile.idx") != 0)
if(remove("WFMHFILE.IDX") != 0)
{
printf("** Can't remove old index file.\n");
chdir(CurrentDir);
#ifdef AMIGA
exit(EXIT_WARN);
#endif
}
fclose(SpareIdx);
SpareIdx = NULL;
if ((rename("WFMHFil2.idx", "WFMHFile.idx")) != 0)
{
printf("** Can't rename new index.\n");
chdir(CurrentDir);
#ifdef AMIGA
exit(EXIT_WARN);
#endif
}
}
}
}
else
{
free(TempEntry);
printf("** Can't find index file!\n");
chdir(CurrentDir);
exit(EXIT_FAILURE);
}
}
else
{
printf("** Can't allocate work buffer!\n");
chdir(CurrentDir);
exit(EXIT_FAILURE);
}
}
else
{
printf("** Unknown command.\n");
chdir(CurrentDir);
exit(EXIT_FAILURE);
}
chdir(CurrentDir);
exit(EXIT_SUCCESS);
}
/*************************************************************************/
/*
** Tadek - functions
**
** return 0 for success
*/
#ifdef OLD_STYLE
int splitname(readname, basename, splitsize)
char readname[];
char basename[];
int splitsize;
#else
int splitname(char readname[], char basename[], int splitsize)
#endif
{
FILE *RHandle = NULL;
FILE *WHandle = NULL;
int c, i, j, disks, diskcount, rem;
i = RC_FAIL;
if (splitsize != 0)
{
if((st = malloc(sizeof(struct stat))) == NULL)
{
if ((rename(readname, basename)) == 0)
i = RC_SPLITERROR;
return i;
}
if(((stat(readname, st)) == 0) && (st->st_size > splitsize))
{
if((RHandle = fopen(readname, "r")) != 0)
{
disks = (st->st_size/splitsize);
if (rem = ((st->st_size)%splitsize))
++disks;
if(st)
{
free(st);
st = NULL;
}
if (disks > DISKS_MAX)
{
fclose(RHandle);
i = RC_CRAZY;
if ((rename(readname, basename)) == 0)
i = RC_CRAZY_COOL;
return i;
}
for (diskcount = 0; diskcount < disks; ++diskcount)
{
if ((namecount(basename, newname, diskcount) == 0) || ((WHandle = fopen(newname, "w")) == 0))
{
fclose(RHandle);
if ((rename(readname, basename)) == 0)
i = RC_SPLITERROR;
return i;
}
for (j = 0; (j < splitsize) && ((c=fgetc(RHandle)) != EOF); ++j)
{
if ((fputc(c, WHandle)) == EOF)
{
fclose(RHandle);
fclose(WHandle);
remove(newname);
if ((rename(readname, basename)) == 0)
i = RC_SPLITERROR;
return i;
}
}
fclose(WHandle);
if (c == EOF)
{
fclose(RHandle);
if (diskcount == disks-1)
{
remove(readname);
i = RC_OK;
SplitCount++;
}
else
{
remove(newname);
if ((rename(readname, basename)) == 0)
i = RC_SPLITERROR;
}
return i;
}
}
if (rem == 0) /* the missing code - no more */
{ /* chars to write, so no more disks */
i = RC_OK;
SplitCount++;
}
fclose(RHandle);
remove(readname);
}
if(st)
{
free(st);
st = NULL;
}
if ((rename(readname, basename)) == 0)
i = RC_SPLITERROR;
return i;
}
if(st)
{
free(st);
st = NULL;
}
}
if ((rename(readname, basename)) == 0)
i = RC_OK;
return i;
}
/*
** now, let's join files (if needed)
*/
#ifdef OLD_STYLE
int rejoinname(basename, realname)
char basename[];
char realname[];
#else
int rejoinname(char basename[], char realname[])
#endif
{
int i, c, diskcount;
FILE *RHandle = NULL;
FILE *WHandle = NULL;
i = RC_FAIL;
if ((rename(basename, realname)) == 0)
{
i = RC_OK;
return i;
}
for (diskcount = 0; ((namecount(basename, newname, diskcount)) != 0) && ((RHandle = fopen(newname, "r")) !=0); ++diskcount)
{
if (WHandle == NULL)
if ((WHandle = fopen(realname, "w")) == 0)
{
fclose(RHandle);
return i;
}
while ((c=fgetc(RHandle)) != EOF)
fputc(c, WHandle);
fclose(RHandle);
remove(newname);
}
if (WHandle)
{
fclose(WHandle);
SplitCount++;
i = RC_OK;
}
return i;
}
/*
** This is for constructing numbered file names
*/
#ifdef OLD_STYLE
int namecount(base, newname, suffix)
char base[];
char newname[];
int suffix;
#else
int namecount(char base[], char newname[], int suffix)
#endif
{
int i;
strcpy(newname, base);
for (i = 0; newname[i] != 0; ++i)
;
--i;
if (suffix > 9)
--i;
if (suffix > 99)
--i;
if (suffix > DISKS_MAX)
return 0;
if ((sprintf(&newname[i],"%d", suffix)) > 3)
return 0;
return i;
}